package com.eci.context.context.feign;

import com.eci.common.asset.constant.StringConstant;
import com.eci.context.context.filter.SessionHolder;
import com.eci.context.util.RequestsUtil;
import feign.Logger;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import feign.Retryer;
import lombok.extern.slf4j.Slf4j;
import okhttp3.ConnectionPool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.cloud.commons.httpclient.OkHttpClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;

@Configuration
@Slf4j
public class FeignInterceptor implements RequestInterceptor {

    @Value("${eci.okhttp.readTimeoutSec:3}")
    int readTimeout;
    @Value("${eci.okhttp.writeTimeoutSec:3}")
    int writeTimeout;
    @Value("${eci.okhttp.connTimeoutSec:10}")
    int connTimeout;

    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.NONE;
    }

    @Bean
    public Retryer feignRetryer() {
        return new EciRetryer(100, 5000, 2);
    }

    @Override
    public void apply(RequestTemplate template) {
        String currentUser = SessionHolder.getUserStr();
        template.header(StringConstant.Authority.AUTH_USER,currentUser);
        template.header("Content-Type","application/json;charset=UTF-8");
        //添加用户ip
        template.header(RequestsUtil.HEADER_HTTP_CLIENT_IP, SessionHolder.getUserIp());
    }

    @Bean
    @ConditionalOnBean(LogOkInterceptor.class)
    public okhttp3.OkHttpClient okHttpClient(@Autowired
                                             LogOkInterceptor okHttpLoggingInterceptor) {
        okhttp3.OkHttpClient.Builder ClientBuilder = new okhttp3.OkHttpClient.Builder()
                .readTimeout(readTimeout, TimeUnit.SECONDS) //读取超时
                .connectTimeout(writeTimeout, TimeUnit.SECONDS) //连接超时
                .writeTimeout(connTimeout, TimeUnit.SECONDS) //写入超时
                .sslSocketFactory(createSSLSocketFactory(), new TrustAllManager())
                .hostnameVerifier(new OkHttpClientFactory.TrustAllHostnames())
                .connectionPool(new ConnectionPool(10 /*maxIdleConnections*/, 3, TimeUnit.MINUTES))
                .addInterceptor(okHttpLoggingInterceptor);
        return ClientBuilder.build();
    }

    private static SSLSocketFactory createSSLSocketFactory() {
        SSLSocketFactory sSLSocketFactory = null;
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, new TrustManager[]{new TrustAllManager()},
                    new SecureRandom());
            sSLSocketFactory = sc.getSocketFactory();
        } catch (Exception e) {
        }

        return sSLSocketFactory;
    }

    private static class TrustAllManager implements X509TrustManager {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType)

                throws CertificateException {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[]{};
        }
    }
}
